package com.ugoodtech.mdcc.web.service.impl;

import com.google.common.collect.Lists;
import com.mysema.query.BooleanBuilder;
import com.ugoodtech.mdcc.core.domain.PerformanceReport;
import com.ugoodtech.mdcc.core.domain.PerformanceReportRecord;
import com.ugoodtech.mdcc.core.domain.QPerformanceReport;
import com.ugoodtech.mdcc.core.domain.QPerformanceReportRecord;
import com.ugoodtech.mdcc.core.repository.PerformanceReportDetailRepository;
import com.ugoodtech.mdcc.core.repository.PerformanceReportRecordRepository;
import com.ugoodtech.mdcc.core.repository.PerformanceReportRepository;
import com.ugoodtech.mdcc.web.common.BizConstants;
import com.ugoodtech.mdcc.web.exception.BizException;
import com.ugoodtech.mdcc.web.exception.EnumBizError;
import com.ugoodtech.mdcc.web.pojo.vo.PerformancePlanHistoryVO;
import com.ugoodtech.mdcc.web.pojo.vo.PerformancePlanRecordVO;
import com.ugoodtech.mdcc.web.pojo.vo.PerformancePlanVO;
import com.ugoodtech.mdcc.web.pojo.vo.PerformanceReportRecordRequestVO;
import com.ugoodtech.mdcc.web.service.PerformancePlanService;
import com.ugoodtech.mdcc.web.utils.PageInfoWrapper;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class PerformPlanHistoryRecord {

    private static Convert convert = new Convert();
    @Autowired
    private PerformanceReportRepository performanceReportRepository;
    @Autowired
    private PerformanceReportDetailRepository performanceReportDetailRepository;
    @Autowired
    private PerformanceReportRecordRepository performanceReportRecordRepository;
    @Autowired
    @Lazy
    private PerformancePlanService performancePlanService;
    @Autowired
    private PerformancePlanCalculator calculator;
    @Autowired
    private PerformancePlanRecordsFilter filter;

    /**
     * 添加业绩报告记录
     *
     * @param operationType 操作类型 计划预测实际
     * @param employeeName  工作人员名称
     * @param operatorName  操作人员名称
     * @param report        报告
     * @param version       报告版本
     */
    public void addPerformPlanRecord(Integer operationType, String employeeName, String operatorName,
                                     PerformanceReport report, Integer version) {
        PerformanceReportRecord reportRecordDO = new PerformanceReportRecord();
        Date date = Calendar.getInstance().getTime();
        reportRecordDO.setCreateTime(date);
        reportRecordDO.setUpdateTime(date);
        reportRecordDO.setEmployeeName(employeeName);
        reportRecordDO.setOperaterName(operatorName);
        reportRecordDO.setStatus(operationType);
        reportRecordDO.setPerformanceReport(report);
        reportRecordDO.setVersion(version);
        reportRecordDO.setIsDeleted(0);
        reportRecordDO.setOperationTime(date);
        if (log.isDebugEnabled()) {
            log.debug("Insert performance operation record [{}].", reportRecordDO);
        }
        PerformanceReportRecord save = performanceReportRecordRepository.save(reportRecordDO);
        if (save==null) {
            throw new BizException(EnumBizError.OPERATION_FAIL.setDetailErrMsg("添加操作记录失败"));
        }
    }

    public PageInfoWrapper<PerformancePlanHistoryVO> listPerformPlanRecordPage(Integer pageIndex, Integer pageSize,
                                                                               PerformanceReportRecordRequestVO recordRequestVO) {
        // Filter data by year first.
        if (log.isDebugEnabled()) {
            log.debug("Filter performance report data by username [{}] and year [{}].",
                    recordRequestVO.getEmployeeName(), recordRequestVO.getYear());
        }
        List<PerformanceReport> reportDOList =
                filter.getReport(recordRequestVO.getEmployeeName(), recordRequestVO.getYear());
        List<Long> reportIdList = new ArrayList<>(reportDOList.size());
        reportDOList.forEach(performanceReportDO -> reportIdList.add(performanceReportDO.getId()));
        if (CollectionUtils.isEmpty(reportIdList) || CollectionUtils.isEmpty(reportDOList)) {
            return PageInfoWrapper.emptyPageInfoWrapper(pageIndex, pageSize);
        }
        QPerformanceReportRecord qPerformanceReportRecord = QPerformanceReportRecord.performanceReportRecord;
        BooleanBuilder builder = new BooleanBuilder();
        builder.and(qPerformanceReportRecord.performanceReport.id.in(reportIdList));
        if (recordRequestVO.getStartTime()!=null&&recordRequestVO.getEndTime()!=null){
            builder.and(qPerformanceReportRecord.operationTime.between(recordRequestVO.getStartTime(),recordRequestVO.getEndTime()));
        }

        List<Sort.Order> sorts = new ArrayList<>();
        Sort.Order status = new Sort.Order(Sort.Direction.ASC, "status");
        Sort.Order operationTime = new Sort.Order(Sort.Direction.DESC, "operationTime");
        if (!StringUtils.isEmpty(recordRequestVO.getEmployeeName())){
            sorts.add(status);
        }
        sorts.add(operationTime);
        Sort sort = new Sort(sorts);
        PageRequest pageRequest = new PageRequest(pageIndex <= 1 ? 0 : pageIndex - 1, pageSize,sort);
        Page<PerformanceReportRecord> all = performanceReportRecordRepository.findAll(builder,pageRequest );
        List<PerformanceReportRecord> performanceReportRecordDOList = Lists.newArrayList(all);
//        List<PerformanceReportRecord> performanceReportRecordDOList = performanceReportRecordDOMapper
//                .getByReportId(reportIdList, recordRequestVO.getStartTime(), recordRequestVO.getEndTime(),
//                        PageInfoWrapper.getStartIndex(pageIndex, pageSize), pageSize);
        return PageInfoWrapper.<PerformancePlanHistoryVO>builder()
                .pageIndex(pageIndex == null ? 1 : pageIndex)
                .pageSize(pageSize == null ? 10 : pageSize)
                .list(convert.convertToVOList(performanceReportRecordDOList))
                .total(all.getTotalElements())
                .build();
    }

    /**
     * 获取某一个历史记录修改的信息
     */
    public PerformancePlanRecordVO getReportOfSomeVersion(Long historyId) {
        PerformanceReportRecord performanceReportRecordDO = performanceReportRecordRepository.findOne(historyId);
        if (performanceReportRecordDO == null) {
            return new PerformancePlanRecordVO();
        }
        return getReportOfSomeVersion(performanceReportRecordDO.getVersion(),
                performanceReportRecordDO.getPerformanceReport().getId());
    }

    /**
     * 获取某一报告的某一版本, 并标记其中和上个版本相比修改过的地方
     */
    public PerformancePlanRecordVO getReportOfSomeVersion(Integer version, Long reportId) {
        PerformancePlanRecordVO recordVO = new PerformancePlanRecordVO();
        PerformanceReport reportDO = performancePlanService.getPlan(reportId);
        PerformancePlanVO planVO = filter.calculateHint(
                filter.filterDataWhenGetMonthPlanHistory
                        (Arrays.asList(filter.sortData(
                                calculator.checkSeasonAnnualModification(
                                        calculator.fillInDataSimply(
                                                filter
                                                        .getReportOfSomeVersion(Arrays.asList(version, version - 1), reportId),
                                                reportDO.getYear())))))).get(0);
        recordVO.setData(planVO.getData());
        BeanUtils.copyProperties(planVO, recordVO);
        recordVO.setYear(reportDO.getYear());
        recordVO.setOperationName(BizConstants.PerformancePlan.getOperationType(reportDO.getStatus()));
        return recordVO;
    }

    public static class Convert {

        public PerformancePlanHistoryVO convertToVO(
                PerformanceReportRecord performanceReportRecordDO) {
            PerformancePlanHistoryVO performancePlanRecordVO = new PerformancePlanHistoryVO();
            BeanUtils.copyProperties(performanceReportRecordDO, performancePlanRecordVO);
            return performancePlanRecordVO;
        }

        public List<PerformancePlanHistoryVO> convertToVOList(
                List<PerformanceReportRecord> performanceReportRecordDOS) {
            List<PerformancePlanHistoryVO> performancePlanRecordVOList = new ArrayList<>(
                    performanceReportRecordDOS.size());
            performanceReportRecordDOS.forEach(performanceReportRecordDO ->
                    performancePlanRecordVOList.add(
                            PerformancePlanHistoryVO.builder()
                                    .employeeName(performanceReportRecordDO.getEmployeeName())
                                    .operaterName(performanceReportRecordDO.getOperaterName())
                                    .operationTime(performanceReportRecordDO.getOperationTime())
                                    .id(performanceReportRecordDO.getId())
                                    .performanceReportId(performanceReportRecordDO.getPerformanceReport().getId())
                                    .status(performanceReportRecordDO.getStatus())
                                    .build())
            );
            return performancePlanRecordVOList;
        }
    }


}
